/* test_sha1.c
**
** Copyright (c) 2007, Meadhbh S. Hamrick
** All rights reserved.
** 
** Redistribution  and  use  in  source  and  binary  forms,  with  or  without
** modification, are permitted provided that the following conditions are met:
** 
**  * Redistributions of  source code must  retain the above  copyright notice,
**    this list of conditions and the following disclaimer.
** 
**  * Redistributions in binary form must reproduce the above copyright notice,
**    this list of conditions and the following disclaimer in the documentation
**    and/or other materials provided with the distribution.
** 
**  * Neither the  name of  Project Meadhbh  nor the names of  its contributors
**    may be used  to endorse  or promote  products derived from this  software
**    without specific prior written permission.
** 
** THIS SOFTWARE IS PROVIDED BY  THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY  EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT  LIMITED TO, THE
** IMPLIED WARRANTIES  OF MERCHANTABILITY AND FITNESS FOR  A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO  EVENT SHALL THE  COPYRIGHT OWNER OR  CONTRIBUTORS BE
** LIABLE  FOR  ANY  DIRECT,   INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
** CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,  PROCUREMENT  OF
** SUBSTITUTE GOODS  OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
** INTERRUPTION)  HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN
** CONTRACT,  STRICT LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE OR  OTHERWISE)
** ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
** 
** $Id: test_sha1.c 53 2007-09-01 07:48:29Z msh.mobile $
*/

/** \file test_sha1.c
**  \brief Test SHA1 Cryptographic Hash Functions
**
** This   file   implements   the    tests   that   are   referenced   in
** test_crypto.c.   It  is  assumed   that  the   initalization  function
** suite_sha1_init()   will  be   called  before   any  of   the  test_*()
** functions. The initialization function does all the "heavy lifting" of
** creating  contexts  and hashing  test  vectors.  The individual  tests
** simply  compare output and  intermediate values  with known  good test
** values.
** 
** "Canonical"  test  vectors are  provided  in  the  inputs and  outputs
** arrays.   The inputs array  is an  array of  known strings  that, when
** hashed, are supposed to generate known values.  We're using the values
** from FIPS 180-2,  it's as close to authoratative as  we could find. To
** test the hashing functions, the suite_sha1_init() function hashes each
** string in the inputs array and places the result in the actual_outputs
** array.  In the  test_sha1_fips_vectors() function,  we  simply compare
** what  we generated  in the  actual_outputs array  with the  known good
** values in the outputs array.
** 
** Numerous  tests for cloning  behavior are  performed. Cloning  is used
** extensively in  these tests.  If it doesn't  work, then  it's unlikely
** that anything  will work. But we perform  a number of tests  to see if
** there are particular problems with cloning before or after various sha1
** function calls.
** 
** We test the mc_mic_sha1_clear() function by clearing a used context and
** then  comparing it  with a  newly initialized  context. Note  that the
** clear function  simply reinitializes a  context to it's  default state
** rather than zeroing memory.
** 
** The  mc_mic_sha1_initialize() function is  tested with  the known-value
** checks mentioned above. We also  verify that memory is properly zeroed
** out.
** 
** Finally,  the mc_mic_sha1_update()  function  is tested  by looking  at
** intermediate and final results in sha1 contexts.
*/

/* Macro Definitions */
#define MC_MIC_SHA1_TEST_MAX_CONTEXTS 11
#define MC_MIC_SHA1_TEST_MAX_VECTORS 3

/* File Includes */
#include <string.h>
#include "mutil.h"
#include "mcrypto/sha1.h"
#include "test_sha1.h"
#include <CUnit/CUnit.h>
#include <stdlib.h>
#include <stdio.h>

/* Typedefs, Structs, Unions, Enums, etc. */

/* Static Function Prototypes */

/* Variable Declarations */
tMCSha1 sha1_actual_contexts [ MC_MIC_SHA1_TEST_MAX_CONTEXTS ];
tMCSha1 sha1_contexts [ MC_MIC_SHA1_TEST_MAX_CONTEXTS ] = {
  {
    .count = 0x0000000000000000LL,
    .data.asLongLong = {
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0x67452301,
      0xEFCDAB89,
      0x98BADCFE,
      0x10325476,
      0xC3D2E1F0,
    }
  },
  {
    .count = 0x0000000000000000LL,
    .data.asLongLong = {
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0x67452301,
      0xEFCDAB89,
      0x98BADCFE,
      0x10325476,
      0xC3D2E1F0,
    }
  },
  {
    .count = 0x0000000000000003LL,
    .data.asLongLong = {
      0x6162630000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0x67452301,
      0xEFCDAB89,
      0x98BADCFE,
      0x10325476,
      0xC3D2E1F0,
    }
  },
  {
    .count = 0x0000000000000003LL,
    .data.asLongLong = {
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0xA9993E36,
      0x4706816A,
      0xBA3E2571,
      0x7850C26C,
      0x9CD0D89D,
    }
  },
  {
    .count = 0x0000000000000038LL,
    .data.asLongLong = {
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0x84983E44,
      0x1C3BD26E,
      0xBAAE4AA1,
      0xF95129E5,
      0xE54670F1,
    }
  },
  {
    .count = 0x0000000000000010LL,
    .data.asLongLong = {
      0x6162636462636465LL,
      0x6364656664656667LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0x67452301,
      0xEFCDAB89,
      0x98BADCFE,
      0x10325476,
      0xC3D2E1F0,
    }
  },
  {
    .count = 0x0000000000000038LL,
    .data.asLongLong = {
      0x6162636462636465LL,
      0x6364656664656667LL,
      0x6566676866676869LL,
      0x6768696A68696A6BLL,
      0x696A6B6C6A6B6C6DLL,
      0x6B6C6D6E6C6D6E6FLL,
      0x6D6E6F706E6F7071LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0x67452301,
      0xEFCDAB89,
      0x98BADCFE,
      0x10325476,
      0xC3D2E1F0,
    }
  },
  {
    .count = 0x0000000000000038LL,
    .data.asLongLong = {
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0x84983E44,
      0x1C3BD26E,
      0xBAAE4AA1,
      0xF95129E5,
      0xE54670F1,
    }
  },
  {
    .count = 0x0000000000000000LL,
    .data.asLongLong = {
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0x67452301,
      0xEFCDAB89,
      0x98BADCFE,
      0x10325476,
      0xC3D2E1F0,
    }
       },
  {
    .count = 0x0000000000000000LL,
    .data.asLongLong = {
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0x67452301,
      0xEFCDAB89,
      0x98BADCFE,
      0x10325476,
      0xC3D2E1F0,
    }
  },
  {
    .count = 0x0000000000000010LL,
    .data.asLongLong = {
      0x6162636462636465LL,
      0x6364656664656667LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL,
      0x0000000000000000LL
    },
    .state = {
      0x67452301,
      0xEFCDAB89,
      0x98BADCFE,
      0x10325476,
      0xC3D2E1F0,
    }
  }
};

uint8_t *sha1_inputs [ MC_MIC_SHA1_TEST_MAX_VECTORS ] = {
  (uint8_t *) "abc",
  (uint8_t *) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
  (uint8_t *) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
};

uint8_t sha1_actual_outputs [ MC_MIC_SHA1_TEST_MAX_VECTORS ][20];

uint8_t sha1_outputs [ MC_MIC_SHA1_TEST_MAX_VECTORS ][20] = {
    { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
    { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
    { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
};

/* Function Definitions */

/** \fn int suite_sha1_init( void )
**  \brief Calls various sha1 functions in preparation for value checking.
**  \returns 0 (success)
** 
** This is  the function where "rubber  meets the road." We  call all the
** functions  under test  in this  initialization function  and  in later
** tests simply compare the values we get with known good values.
** 
** We have  a series of tMCSha1  data structures used to  hold the hashing
** context after  various operations. This function  generally performs a
** function,  then clones  the context.  We do  this to  save information
** about the intermediate state of the hash functions. This can help with
** debugging if something  goes wrong. IT IS NOT  THE GENERAL PATTERN FOR
** USING THIS API.
** 
** The algorithm-specific  functions don't  return error codes  and don't
** check parameters. Ergo, we won't  know if there's a failure during the
** init routine's run. We get that info later in the test_*()
** functions.
*/

int suite_sha1_init() {
  uint32_t i;

  /* Initialize the first context */
  mc_mic_sha1_initialize( & (sha1_actual_contexts[0]) );

  /* Clone a context that has not been used */
  mc_mic_sha1_clone( & (sha1_actual_contexts[1]), & (sha1_actual_contexts[0]) ); 

  /* Clone a context for vector 0 */
  mc_mic_sha1_clone( & (sha1_actual_contexts[2]), & (sha1_actual_contexts[0]) );

  /* Hash "abc" (vector 0) */
  mc_mic_sha1_update( & (sha1_actual_contexts[2]), (uint8_t *) sha1_inputs[ 0 ], (uint32_t) strlen( (const char *) sha1_inputs[ 0 ] ) );

  /* Clone this context */
  mc_mic_sha1_clone( & (sha1_actual_contexts[3]), & (sha1_actual_contexts[2]) );

  /* Produce Digest for vector 0 */
  mc_mic_sha1_digest( & (sha1_actual_contexts[3]), (uint8_t *) sha1_actual_outputs[0] );

  /* Clone a context for vector 1 */
  mc_mic_sha1_clone( & (sha1_actual_contexts[4]), & (sha1_actual_contexts[0]) );

  /* Hash 16 bytes of "abcdefghijklmnopqrstuvwxyz" (vector 4) */
  mc_mic_sha1_update( & (sha1_actual_contexts[4]), (uint8_t *) sha1_inputs[1], 16 );

  /* Clone a context that has been updated with exactly 16 bytes, but not
     finalized */
  mc_mic_sha1_clone( & (sha1_actual_contexts[5]), & (sha1_actual_contexts[4]) );

  /* Clone it again so we have something to use */

  mc_mic_sha1_clone( & (sha1_actual_contexts[10]), & (sha1_actual_contexts[4]) );
  /* Hash the remainder of vector 1 */
  mc_mic_sha1_update( & (sha1_actual_contexts[4]), (uint8_t *) & (sha1_inputs[1][16]), (uint32_t) strlen( (const char *) &( sha1_inputs[1][16] ) ) );

  /* Clone a context that has been updated twice, but not finalized */
  mc_mic_sha1_clone( & (sha1_actual_contexts[6]), & (sha1_actual_contexts[4]) );

  /* Produce digest for vector 1 */
  mc_mic_sha1_digest( & (sha1_actual_contexts[4]), (uint8_t *) sha1_actual_outputs[1] );

  /* Clone a context that has been finalized */
  mc_mic_sha1_clone( & (sha1_actual_contexts[7]), & (sha1_actual_contexts[4]) );

  /* Clone a context for vector 2 */
  mc_mic_sha1_clone( & (sha1_actual_contexts[8]), & (sha1_actual_contexts[0]) );

  /* Hash one million "a" characters */
  for( i = 0; i < 10000; i++ ) {
    mc_mic_sha1_update( & (sha1_actual_contexts[8]), (uint8_t *) sha1_inputs[2], (uint32_t) strlen( (const char *) sha1_inputs[2] ) );
  }

  /* Produce digest for vector 2 */
  mc_mic_sha1_digest( & (sha1_actual_contexts[8]), (uint8_t *) sha1_actual_outputs[2] );

  /* Clear context 8 */
  mc_mic_sha1_clear( & (sha1_actual_contexts[8]) );

  /* Clone a context that's been cleared */
  mc_mic_sha1_clone( & (sha1_actual_contexts[9]), &(sha1_actual_contexts[8]) );

  return( 0 );
}

/** \fn void test_sha1_fips_vectors( void )
**  \brief Tests for compatibility with test vectors provided in FIPS 180-2
** 
** During the init function's run, we hashed a number of "canonical" test
** vectors listed in FIPS 180-2.  In this function, we simply compare the
** results  of our  computation (in  the actual_outputs  array)  with the
** known-good values given in the FIPS document (in the outputs array).
*/

void test_sha1_fips_vectors( ) {

  CU_ASSERT_EQUAL( 0, memcmp( sha1_outputs[0], sha1_actual_outputs[0], 20 ) );
  CU_ASSERT_EQUAL( 0, memcmp( sha1_outputs[1], sha1_actual_outputs[1], 20 ) );
  CU_ASSERT_EQUAL( 0, memcmp( sha1_outputs[2], sha1_actual_outputs[2], 20 ) );
}

/** \fn void test_mc_mic_sha1_clone( void )
**  \brief Tests our ability to clone hash contexts
** 
** In this  test, we  look to  see if our  ability to  copy a  context is
** dependent on  the state of the  context. I would be  very surprised if
** this fails.
*/

void test_mc_mic_sha1_clone( ) {
  /* Can we clone a newly initialized context? */
  CU_ASSERT_EQUAL( 0, memcmp( & (sha1_actual_contexts[0]), & (sha1_actual_contexts[1]), sizeof( tMCSha1 ) ) );

  /* Can we clone a context that's been updated with less than one block? */
  CU_ASSERT_EQUAL( 0, memcmp( & (sha1_actual_contexts[10]), & (sha1_actual_contexts[5]), sizeof( tMCSha1 ) ) );
  
  /* Can we clone a context that's been finalized? */
  CU_ASSERT_EQUAL( 0, memcmp( & (sha1_actual_contexts[4]), & (sha1_actual_contexts[7]), sizeof( tMCSha1 ) ) );

  /* Can we clone a context that's been cleared? */
  CU_ASSERT_EQUAL( 0, memcmp( & (sha1_actual_contexts[8]), & (sha1_actual_contexts[9]), sizeof( tMCSha1 ) ) );
}

/** \fn void test_mc_mic_sha1_clear( void )
**  \brief Tests to ensure that sensitive data is cleared
** 
** We test  the mc_mic_sha1_clear() function  by comparing the state  of a
** SHA1 context  after a  call to mc_mic_sha1_clear()  with the state  of a
** context  after a  call to  mc_mic_sha1_initialize(). If  they're equal,
** then we're good.
*/

void test_mc_mic_sha1_clear( ) {
  /* Compare context 0 (newly initialized) with context 16 (newly cleared) */
  CU_ASSERT_EQUAL( 0, memcmp( & (sha1_actual_contexts[0]), & (sha1_actual_contexts[8]), sizeof( tMCSha1 ) ) );
}

/** \fn void test_mc_mic_sha1_initialize( void )
**  \brief Tests the ability to initiailze a newly allocated hashing context. 
*/

void test_mc_mic_sha1_initialize( ) {
  /* Count should be zero */
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].count );

  /* Data values should be zero */
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[ 0] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[ 1] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[ 2] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[ 3] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[ 4] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[ 5] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[ 6] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[ 7] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[ 8] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[ 9] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[10] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[11] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[12] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[13] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[14] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[15] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[16] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[17] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[18] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[19] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[20] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[21] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[22] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[23] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[24] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[25] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[26] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[27] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[28] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[29] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[30] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[31] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[32] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[33] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[34] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[35] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[36] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[37] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[38] );
  CU_ASSERT_EQUAL( 0LL, sha1_actual_contexts[0].data.asLongLong[39] );

  /* State values are well known */
  CU_ASSERT_EQUAL( 0x67452301, sha1_actual_contexts[0].state[0] );
  CU_ASSERT_EQUAL( 0xEFCDAB89, sha1_actual_contexts[0].state[1] );
  CU_ASSERT_EQUAL( 0x98BADCFE, sha1_actual_contexts[0].state[2] );
  CU_ASSERT_EQUAL( 0x10325476, sha1_actual_contexts[0].state[3] );
  CU_ASSERT_EQUAL( 0xC3D2E1F0, sha1_actual_contexts[0].state[4] );
}

/** \fn void test_mc_mic_sha1_update( void )
**  \brief Tests the hash update function
** 
** Testing  the update  function is  fairly straight-forward.  We  have a
** series  of  known-good values  for  SHA1  contexts  at different  times
** throught the hashing  process. We simply compare the  test states with
** the known good values.
*/

void test_mc_mic_sha1_update( ) {

#ifndef WORDS_BIGENDIAN
  uint32_t j;

  for( j = 0; j < 5; j++ ) {
    sha1_actual_contexts[3].state[j] = MU_END32( sha1_actual_contexts[3].state[j] );
    sha1_actual_contexts[4].state[j] = MU_END32( sha1_actual_contexts[4].state[j] );
    sha1_actual_contexts[7].state[j] = MU_END32( sha1_actual_contexts[7].state[j] );
  }

  for( j = 0; j < 40; j++ ) {
    sha1_actual_contexts[2].data.asLongLong[j] = MU_END64( sha1_actual_contexts[2].data.asLongLong[j] );
    sha1_actual_contexts[5].data.asLongLong[j] = MU_END64( sha1_actual_contexts[5].data.asLongLong[j] );
    sha1_actual_contexts[6].data.asLongLong[j] = MU_END64( sha1_actual_contexts[6].data.asLongLong[j] );
    sha1_actual_contexts[10].data.asLongLong[j] = MU_END64( sha1_actual_contexts[10].data.asLongLong[j] );
  }
#endif

  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[0] ), (uint8_t *) &( sha1_contexts[0] ), sizeof( tMCSha1 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[1] ), (uint8_t *) &( sha1_contexts[1] ), sizeof( tMCSha1 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[2] ), (uint8_t *) &( sha1_contexts[2] ), sizeof( tMCSha1 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[3] ), (uint8_t *) &( sha1_contexts[3] ), sizeof( tMCSha1 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[4] ), (uint8_t *) &( sha1_contexts[4] ), sizeof( tMCSha1 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[5] ), (uint8_t *) &( sha1_contexts[5] ), sizeof( tMCSha1 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[6] ), (uint8_t *) &( sha1_contexts[6] ), sizeof( tMCSha1 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[7] ), (uint8_t *) &( sha1_contexts[7] ), sizeof( tMCSha1 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[8] ), (uint8_t *) &( sha1_contexts[8] ), sizeof( tMCSha1 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[9] ), (uint8_t *) &( sha1_contexts[9] ), sizeof( tMCSha1 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha1_actual_contexts[10] ), (uint8_t *) &( sha1_contexts[10] ), sizeof( tMCSha1 ) ) );
}
